package db

import (
	"context"
	"enode/store/small_file/models"
	"fmt"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"sync"
)

func opendb(name string) (*gorm.DB, error) {
	db, err := gorm.Open(sqlite.Open(name), &gorm.Config{})
	if err != nil {
		return nil, err
	}
	_ = db.Exec("PRAGMA synchronous = off;")
	return db, err
}

type sqliteHandle struct {
	db *gorm.DB
	sync.Mutex
}

func NewSqliteHandle(name string) *sqliteHandle {
	db, err := opendb(name)
	if err != nil {
		return nil
	}
	return &sqliteHandle{db: db}
}

func (s *sqliteHandle) MigratorTable(ctx context.Context) {
	s.db.WithContext(ctx).AutoMigrate(
		&models.FileIndex{},
		&models.Blob{},
	)
}
func (s *sqliteHandle) CleanData() {
	s.db.Exec("DELETE FROM file_indices")
	s.db.Exec("DELETE FROM blobs")
}

func (s *sqliteHandle) InserFileIndex(ctx context.Context, index models.FileIndex) error {
	s.Lock()
	defer s.Unlock()

	index.Del = false
	tx := s.db.WithContext(ctx).Create(&index)
	if tx.Error != nil {
		fmt.Println(tx.Error)
	}
	return tx.Error
}
func (s *sqliteHandle) AppendToBlob(ctx context.Context, storePath, expire string, size int64) (int64, error) {
	blob := models.Blob{
		StorePath: storePath,
		Expire:    expire,
		CurPost:   0,
		DelCount:  0,
		FileCount: 0,
	}
	s.Lock()
	defer s.Unlock()

	db2 := s.db.Begin()

	tx := db2.WithContext(ctx).Model(&models.Blob{}).
		Where("store_path = ?", storePath).FirstOrCreate(&blob)
	if tx.Error != nil {
		db2.Rollback()
		return 0, tx.Error
	}
	var oldPost = blob.CurPost
	blob.CurPost += size
	blob.FileCount = blob.FileCount + 1
	tx = db2.WithContext(ctx).Model(&models.Blob{}).Where("store_path = ?", storePath).Updates(&blob)
	if tx.Error != nil {
		db2.Rollback()
		return 0, tx.Error
	}
	return oldPost, db2.Commit().Error
}

func (s *sqliteHandle) MarkDel(ctx context.Context, pieceId string) error {
	s.Lock()
	defer s.Unlock()
	tx := s.db.WithContext(ctx).Model(&models.FileIndex{}).
		Where("piece_id = ?", pieceId).UpdateColumn("del", true)
	if tx.Error != nil {
		fmt.Println(tx.Error)
	}

	//tx := s.db.WithContext(ctx).Model(&models.Blob{}).
	//	Where("store_path = ?", storePath)

	return tx.Error
}
func (s *sqliteHandle) CleanExpire(ctx context.Context, expire string) error {
	s.Lock()
	defer s.Unlock()
	tx := s.db.Debug().WithContext(ctx).Where("expire = ?", expire).Delete(&models.FileIndex{})
	if tx.Error != nil {
		fmt.Println(tx.Error)
	}
	tx = s.db.Debug().WithContext(ctx).Where("expire = ?", expire).Delete(&models.Blob{})
	if tx.Error != nil {
		fmt.Println(tx.Error)
	}
	return tx.Error
}
func (s *sqliteHandle) GetFileInfo(ctx context.Context, pieceId string) (*models.FileIndex, error) {
	s.Lock()
	defer s.Unlock()

	index := models.FileIndex{}
	tx := s.db.WithContext(ctx).Model(&models.FileIndex{}).
		Where("piece_id = ?", pieceId).First(&index)
	if tx.Error != nil {
		fmt.Println(tx.Error)
		return nil, tx.Error
	}
	return &index, tx.Error
}
